#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <iostream>
#include <sys/epoll.h>
#include <unistd.h>
#include <cstring>

#define MAX_EVENTS 10
#define PORT 8888
#define BUF_SIZE 1024

int setnonblocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1) return -1;
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

int main() {
    int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        perror("bind");
        close(listen_sock);
        exit(EXIT_FAILURE);
    }

    if (listen(listen_sock, SOMAXCONN) == -1) {
        perror("listen");
        close(listen_sock);
        exit(EXIT_FAILURE);
    }

    int epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) {
        perror("epoll_create1");
        close(listen_sock);
        exit(EXIT_FAILURE);
    }

    struct epoll_event event;
    event.data.fd = listen_sock;
    event.events = EPOLLIN | EPOLLET; // 边缘触发模式
    //event.events = EPOLLIN; // 水平触发模式
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &event) == -1) {
        perror("epoll_ctl: listen_sock");
        close(listen_sock);
        close(epoll_fd);
        exit(EXIT_FAILURE);
    }

    struct epoll_event events[MAX_EVENTS];

    while (1) {
        int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        if (num_events == -1) {
            perror("epoll_wait");
            break;
        }

        for (int i = 0; i < num_events; ++i) {
            if (events[i].data.fd == listen_sock && (events[i].events & EPOLLIN)) {
                // 处理新连接
                struct sockaddr_in client_addr;
                socklen_t client_len = sizeof(client_addr);
                int client_fd = accept(listen_sock, (struct sockaddr *)&client_addr, &client_len);
                if (client_fd != -1) {
                    // 设置socket为非阻塞
                    setnonblocking(client_fd);
                    struct epoll_event event;
                    event.data.fd = client_fd;
                    event.events = EPOLLIN | EPOLLET;
                    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &event) == -1) {
                        perror("epoll_ctl: client_fd");
                        close(client_fd);
                    }
                }
            } else if (events[i].events & EPOLLIN) {
                // // 读取客户端数据
                // int client_fd = events[i].data.fd;
                // char buf[BUF_SIZE];
                // ssize_t count = read(client_fd, buf, sizeof(buf));
                // if (count > 0) {
                //     printf("Server Received from client: %.*s\n", (int)count, buf);
                // } else if (count == 0 || errno == ECONNRESET) {
                //     // 客户端关闭连接
                //     printf("Client closed connection\n");
                //     epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
                //     close(client_fd);
                // }
                int client_fd = events[i].data.fd;
                char buf[BUF_SIZE];

                while (true) {
                    ssize_t count = read(client_fd, buf, sizeof(buf));
                    if (count > 0) {
                        // 成功读取到数据
                        printf("Server Received from client: %.*s\n", (int)count, buf);
                    } else if (count == 0) {
                        // 客户端关闭连接
                        printf("Client closed connection\n");
                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
                        close(client_fd);
                        break;
                    } else {
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
                            // 数据已全部读取完毕
                            printf("read complete\n");
                            break;
                        } else {
                            // 其他错误处理
                            perror("read error");
                            epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
                            close(client_fd);
                            break;
                        }
                    }
                }
            }
        }
    }

    close(listen_sock);
    close(epoll_fd);
    return 0;
}